#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <wait.h>
#include <string.h>

#define MAX_LINE 80

int ptr_list = 0;
char hisList[10][MAX_LINE];

int main() {
  char str[MAX_LINE];
  int args = 0;
  char *argv[MAX_LINE/2+1];
  int should_run = 1;
  int num = 0;
  while( should_run ) {
    printf("osh>");
    fflush(stdout);

    memset(str, 0, sizeof(str));
    
    // read args
    int p1 = 0;
    while( (str[p1] = getchar())!='\n' ) ++ p1;
    str[p1] = '\0';

    if(strcmp(str,"history") == 0) {
      // printf("in his\n");
      for(int i = (ptr_list-1+10)%10, j = (10<num?10:num)-1; j >= 0 ; -- j, i = (i - 1 + 10)%10 ) {
        printf("%d %s\n",j,hisList[i]);
      }
      continue;
    }
    else if(strcmp(str,"!!") == 0) {
      if(num == 0) {
        printf("No commands in history.\n");
        continue;
      }
      int tt = (ptr_list-1+10)%10;
      memcpy(str, hisList[tt], sizeof(str));
      printf("osh>%s\n",str);
    }
    else if(str[0] == '!' && str[1] != '!') {
      if(num < str[1]-'0') {
        printf("No such command in history.\n");
        continue;
      }
      for(int i = (ptr_list-1+10)%10, j = (10<num?10:num)-1; j >= 0 ; -- j, i = (i - 1 + 10)%10 ) {
        // j,hisList[i];
        if(j == str[1]-'0') {
          memcpy(str, hisList[i], sizeof(str));
          break;
        }
      }
      printf("osh>%s\n",str);
    }
    else {
      memcpy(hisList[ptr_list], str, sizeof(str));
      ptr_list = (ptr_list + 1) % 10;
      num ++;
      p1 = MAX_LINE-1;
    }

    args = 0;
    int p2 = 0;
    while(p2 < p1) {
      while(p2 < p1 && str[p2] == ' ') str[p2]='\0', ++ p2;
      if(p2 < p1) argv[args++] = str+p2;
      while(p2 < p1 && str[p2] != ' ') ++ p2;
    }
    argv[args] = NULL;
    str[p1] = '\0';

    // for(int i = 0; i < args; ++ i) {
    //   printf("pram: %s\n",argv[i]);
    // }

    if(args == 1 && strcmp(argv[0],"exit") == 0) {
      should_run = 0;
      return 0;
    }

    int pid = fork();
    if (pid < 0) {
      fprintf(stderr, "Fork Failed");
      continue;
    }
    else if (pid == 0) {
      // child process
      // printf("child process\n");
      execvp(argv[0],argv);
      return 0;
    }
    else {
      if( (*argv[args-1]) != '&' ) {
        wait(NULL);
      }
    }
  }
}
